<template>
  <div class="container">
    <div id="mountNode" style="width: 100%"></div>
    <div class="buttonWrapper">
      <el-button type="primary" @click="changeShape('myReact')"
        >自定义矩形</el-button
      >
      <el-button type="primary" @click="changeShape('triangle')"
        >自定义三角</el-button
      >
      <el-button type="primary" @click="changeShape('tree')"
        >自定义形状(树)</el-button
      >
      <el-button type="primary" @click="changeShape('roundReact')"
        >圆角矩形</el-button
      >
    </div>
  </div>
</template>

<script>
import { Chart, registerShape } from "@antv/g2";
// 获取 cfg 中的 fill 属性
function getFillAttrs(cfg) {
  return {
    ...cfg.defaultStyle,
    ...cfg.style,
    fill: cfg.color,
    fillOpacity: cfg.opacity,
  };
}
export default {
  data() {
    return {
      chart: null,
      data: [
        { genre: "Sports", sold: 27500 },
        { genre: "Strategy", sold: 11500 },
        { genre: "Action", sold: 6000 },
        { genre: "Shooter", sold: 3500 },
        { genre: "Other", sold: 1500 },
      ],
    };
  },
  created() {
    this.registerReact();
    this.registerTrianglet();
    this.registerTree();
    this.registerRoundReact()
  },
  mounted() {
    this.chart = new Chart({
      container: "mountNode",
      autoFit: true,
      // 容器的高度
      height: 500,
      // 图表的外侧内边距
      padding: [40, 80, 80, 80],
    });

    this.chart.data(this.data);
    this.chart
      .interval()
      .position("genre*sold")
      .color("genre")
      .shape("roundReact");
    this.chart.render();
  },
  methods: {
    // 切换形状
    changeShape(type) {
      this.chart.clear();
      this.chart
        .interval()
        .position("genre*sold")
        .color("genre")
        .shape(type);
      this.chart.render();
    },
    // 注册自定义矩形
    registerReact() {
      registerShape("interval", "myReact", {
        // 1. 定义关键点
        // 不同类型的图形组成单元不同，以 interval 为例子有: x (图形中心 x 坐标); y (数据值映射的 y 坐标); y0 (数据起始 y 坐标); size (设置的图形宽度)
        // 通过这些基础值，来给你的自定义图形提供可以计算的位置坐标。以此来完成自定义点的确定。
        getPoints(cfg) {
          const x = cfg.x;
          const y = cfg.y;
          const y0 = cfg.y0;
          const width = cfg.size;
          return [
            { x: x - width / 2, y: y0 },
            { x: x - width / 2, y: y },
            { x: x + width / 2, y: y },
            { x: x + width / 2, y: y0 },
          ];
        },
        // 2. 绘制
        draw(cfg, group) {
          // 这里的 points 对应 getPoints 设置的关键点
          const points = this.parsePoints(cfg.points); // 将0-1空间的坐标转换为画布坐标
          // addShape 可以添加： Circle 圆形；Ellipse 椭圆；Rect 矩形；Line 直线；Polyline 折线；Polygon 多边形；Path 路径；Marker 几何图形；Image 图片；Text 文本；Dom 节点 (SVG)
          // path 的使用参数可参考 https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Paths
          const polygon = group.addShape("path", {
            attrs: {
              path: [
                ["M", points[0].x, points[0].y],
                ["L", points[1].x, points[1].y],
                ["L", points[2].x, points[2].y],
                ["L", points[3].x, points[3].y],
                ["Z"],
              ],
              ...cfg.defaultStyle,
              fill: cfg.color,
            },
          });
          return polygon;
        },
        getMarker(markerCfg) {
          const { color } = markerCfg;
          return {
            // symbol 提供了几个内置的几何图形，详情可参考 G 的 marker
            // circle: 圆形; square: 正方形; diamond: 菱形; triangle: 三角形; triangle-down: 倒三角形
            // 使用如下：

            // symbol:'square',

            // 自定义几何图形
            // x: 中心点 x 坐标; y:中心点 y 坐标; r:几何图形的尺寸;
            symbol: (x, y, r) => {
              return [
                ["M", x, y - 1.5 * r],
                ["L", x, y + 1.5 * r],
                ["L", x + 2 * r, y + 1.5 * r],
                ["L", x + 2 * r, y - 1.5 * r],
                ["Z"],
              ];
            },
            style: {
              stroke: color,
              fill: color,
            },
          };
        },
      });
    },
    // 注册自定义圆角矩形
    registerRoundReact() {
      registerShape("interval", "roundReact", {
        // 2. 绘制
        draw(cfg, container) {
          const attrs = getFillAttrs(cfg);
          const points = this.parsePoints(cfg.points); // 将 0 - 1 的值转换为画布坐标
          const radius = (points[2].x - points[1].x) / 6;
          const temp = [];
          temp.push(['M', points[0].x, points[0].y]);
          temp.push(['L', points[1].x, points[1].y + radius]);
          temp.push(['A', radius, radius, 90, 0, 1, points[1].x + radius, points[1].y]);
          temp.push(['L', points[2].x - radius, points[2].y]);
          temp.push(['A', radius, radius, 90, 0, 1, points[2].x, points[2].y + radius]);
          temp.push(['L', points[3].x, points[3].y]);
          temp.push(['Z']);
          const group = container.addGroup();
          group.addShape('path', {
            attrs: {
              ...attrs,
              path: temp,
            },
          });

          return group;
        },
        getMarker(markerCfg) {
          const { color } = markerCfg;
          return {
            symbol: (x, y, r) => {
              const radius = r/2;
              return [
                ["M", x, y + 1.5 * r],
                ["L", x, y - 1.5 * r],
                // ['A', radius, radius, 0, 0, 1, x + radius, y - 1.5 * r - radius],
                ["L", x + 2 * r, y - 1.5 * r],
                // ['A', radius, radius, 0, 0, 1, x + 2 * r - radius, y - 1.5 * r + radius ],
                ["L", x + 2 * r, y + 1.5 * r],
                ["Z"],
              ];
            },
            style: {
              stroke: color,
              fill: color,
            },
          };
        },
      });
    },
    // 注册自定义三角形状
    registerTrianglet() {
      registerShape("interval", "triangle", {
        // 1. 定义关键点
        getPoints(cfg) {
          const x = cfg.x;
          const y = cfg.y;
          const y0 = cfg.y0;
          const width = cfg.size;
          return [
            { x: x - width / 2, y: y0 },
            { x: x, y: y },
            { x: x + width / 2, y: y0 },
          ];
        },
        // 2. 绘制
        draw(cfg, group) {
          const points = this.parsePoints(cfg.points); // 将0-1空间的坐标转换为画布坐标
          const polygon = group.addShape("path", {
            attrs: {
              path: [
                ["M", points[0].x, points[0].y],
                ["L", points[1].x, points[1].y],
                ["L", points[2].x, points[2].y],
                ["Z"],
              ],
              ...cfg.defaultStyle,
              fill: cfg.color,
            },
          });
          return polygon;
        },
        getMarker(markerCfg) {
          const { color } = markerCfg;
          return {
            symbol: (x, y, r) => {
              return [
                ["M", x, y + r],
                ["L", x + r, y - r],
                ["L", x + 2 * r, y + r],
                ["Z"],
              ];
            },
            style: {
              stroke: color,
              fill: color,
            },
          };
        },
      });
    },
    // 注册自定义树型
    registerTree() {
      registerShape("interval", "tree", {
        // 1. 定义关键点
        getPoints(cfg) {
          const x = cfg.x;
          const y = cfg.y;
          const y0 = cfg.y0;
          const width = cfg.size;
          return [
            { x: x - width / 4, y:  y0  },
            { x: x - width / 4, y:  y / 3 },
            { x: x - 3 * width / 4, y:  y / 3 },
            { x: x - width / 4, y:  3 * y / 4 },
            { x: x - width / 2, y:  3 * y / 4 },
            { x: x , y: y },
            { x: x + width / 2, y:  3 * y / 4 },
            { x: x + width / 4, y:  3 * y / 4 },
            { x: x + 3 * width / 4, y:  y / 3 },
            { x: x + width / 4, y:  y / 3 },
            { x: x + width / 4, y:  y0  },
          ];
        },
        // 2. 绘制
        draw(cfg, group) {
          const points = this.parsePoints(cfg.points); // 将0-1空间的坐标转换为画布坐标
          console.log(points)
          const polygon = group.addShape("path", {
            attrs: {
              path: [
                ["M", points[0].x, points[0].y],
                ["L", points[1].x, points[1].y],
                ["L", points[2].x, points[2].y],
                ["L", points[3].x, points[3].y],
                ["L", points[4].x, points[4].y],
                ["L", points[5].x, points[5].y],
                ["L", points[6].x, points[6].y],
                ["L", points[7].x, points[7].y],
                ["L", points[8].x, points[8].y],
                ["L", points[9].x, points[9].y],
                ["L", points[10].x, points[10].y],
                ["Z"],
              ],
              ...cfg.defaultStyle,
              fill: cfg.color,
            },
          });
          return polygon;
        },
        getMarker(markerCfg) {
          const { color } = markerCfg;
          return {
            symbol: (x, y, r) => {
              return [
                ["M", x, y + r],
                ["L", x + r, y - r],
                ["L", x + 2 * r, y + r],
                ["Z"],
              ];
            },
            style: {
              stroke: color,
              fill: color,
            },
          };
        },
      });
    },
  },
};
</script>

<style lang="scss" scoped>
.container {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  .title_bar {
    width: 100%;
    margin-bottom: 20px;
    .main_title {
      width: 100%;
      text-align: center;
      font-size: 40px;
      color: #333333;
    }
    .sub_title {
      width: 100%;
      text-align: center;
      font-size: 28px;
      margin-top: 18px;
      color: #999999;
    }
  }
}
</style>
